package com.mingke.chat.server;

import com.google.gson.Gson;
import com.mingke.chat.handler.WriteHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * @author mingke
 * @function TODO
 * @date 2021/12/20
 */
public class EasyChatClientChannelTool {
    /** 全局单例*/
    public final static EasyChatClientChannelTool instance = new EasyChatClientChannelTool();
    //日志框架
    private final Logger log = LoggerFactory.getLogger(this.getClass());
    /** 用户number和Channel的映射*/
    private Map<Integer, AsynchronousSocketChannel> channelMap = new HashMap<>();
    private Map<Integer, Integer> hashCodeMap = new HashMap<>();

    /** 私有构造器*/
    private EasyChatClientChannelTool() {
    }

    /**
     * 添加对应用户的Chanel到Map中
     * @param userNumber 用户的number
     * @param channel 用户的AIO信道
     */
    public void addChannel(Integer userNumber, AsynchronousSocketChannel channel) {
        channelMap.put(userNumber, channel);
        hashCodeMap.put(channel.hashCode(), userNumber);
    }

    /**
     * 移除对应用户number的信道
     * @param userNumber 用户number
     */
    public void removeChannel(Integer userNumber) {
        channelMap.remove(userNumber);
    }

    /**
     * 获取到对应用户的信道
     * @param number 用户的ID
     * @return 用户对应的信道
     */
    public AsynchronousSocketChannel getChannel(Integer number) {return channelMap.get(number);}

    /**
     * 根据Channel获得用户的number，用户客户端断开连接时用的上
     * @param channel 用户的number
     * @return 用户的number
     */
    public Integer removelChannel(AsynchronousSocketChannel channel) {
        Integer number = hashCodeMap.get(channel.hashCode());
        removeChannel(number);
        return number;
    }

    /**
     * 向指定外设投递消息
     * @param toNumber 目标用户的number
     * @param msg 消息本体
     */
    public void writeToClient(Integer toNumber, Object msg) {
        if(channelMap.containsKey(toNumber)) {
            AsynchronousSocketChannel socketChannel = channelMap.get(toNumber);
            if((socketChannel!=null) && (socketChannel.isOpen())) {
                Gson jsonUtils = new Gson();
                String info = jsonUtils.toJson(msg);
                ByteBuffer byteBuffer = ByteBuffer.wrap(info.getBytes(StandardCharsets.UTF_8));
                socketChannel.write(byteBuffer, null, new WriteHandler());
                log.info("消息投递成功");
            }
        }
    }
}
